import sys

from PyQt5.QtCore import QObject, pyqtSignal, QThread
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayout, QMainWindow, QComboBox, QMessageBox, \
    QVBoxLayout, QPushButton, QFrame

from config import config_path
from system import run_command
from widgets import BrightnessWidget, ContrastWidget, SourceWidget, ResolutionWidget


class DetectScanners(QObject):
    finish_signal = pyqtSignal(dict)

    def run(self):
        import sane
        sane.init()
        scanners = {f'{i[1]} {i[2]}': i[0] for i in sane.get_devices()}
        self.finish_signal.emit(scanners)


class InfoAboutScanner(QObject):
    finish_signal = pyqtSignal(str)

    def run(self):
        current_scanner = self.current_scanner
        print('***', current_scanner)
        scanner_properties = run_command(f"scanimage --device-name='{current_scanner}' -A")
        self.finish_signal.emit(scanner_properties)


class ScannerSettings(QMainWindow):

    def renew_info_about_scanner(self):
        self.status_bar.setText('Обновляется информация о сканере...')
        self.disable_all_widgets()

        self.scanner_settings_thread = QThread(parent=self)
        self.info_about_current_scanner = InfoAboutScanner()
        self.info_about_current_scanner.current_scanner = self.scanners_dict[self.current_scanner]
        self.info_about_current_scanner.moveToThread(self.scanner_settings_thread)
        self.scanner_settings_thread.started.connect(self.disable_all_widgets)
        self.info_about_current_scanner.finish_signal.connect(
            lambda scanner_properties: self.update_scaner_widgets(scanner_properties))
        self.scanner_settings_thread.started.connect(self.info_about_current_scanner.run)
        self.scanner_settings_thread.finished.connect(self.scanner_settings_thread.deleteLater)
        self.info_about_current_scanner.finish_signal.connect(self.info_about_current_scanner.deleteLater)
        self.info_about_current_scanner.finish_signal.connect(lambda: self.status_bar.setText('Готово'))
        self.info_about_current_scanner.finish_signal.connect(self.enable_buttons)
        self.scanner_settings_thread.start()

    def update_scaner_widgets(self, scanner_properties):
        print(scanner_properties)
        if 'failed: Invalid argument' in scanner_properties:
            dlg = QMessageBox()
            dlg.setWindowTitle('Внимание!')
            dlg.setText('Выбранный сканер отсутствует в системе. Попробуйте обновить список сканеров.')
            dlg.exec_()
            return
        self.scanner_params_available = {
            'brightness': False,
            'contrast': False,
            'source': False,
            'resolution': False
        }
        scanner_properties = scanner_properties.split('\n')
        current_scanner = self.scanners_combobox.currentText().strip()
        
        for line in scanner_properties:
            if line.strip().startswith('--brightness'):
                try:
                    current_value = int(line.split('[')[-1].split(']')[0])
                except Exception:
                    current_value = 0
                saved_brightness_value = run_command(f'py-ini-config get {config_path} "{current_scanner}" brightness')
                if saved_brightness_value:
                    current_value = int(saved_brightness_value)
                self.scanner_params_available['brightness'] = True
                self.brightness_widget.brightness_slider.setValue(current_value)
                self.brightness_widget.setEnabled(True)
                print('br')

            if line.strip().startswith('--contrast'):
                try:
                    current_value = int(line.split('[')[-1].split(']')[0])
                except Exception:
                    current_value = 0
                saved_contrast_value = run_command(f'py-ini-config get {config_path} "{current_scanner}" contrast')
                if saved_contrast_value:
                    current_value = int(saved_contrast_value)
                self.scanner_params_available['contrast'] = True
                self.contrast_widget.contrast_slider.setValue(current_value)
                self.contrast_widget.setEnabled(True)
                print('co')

            if line.strip().startswith('--source'):
                self.scanner_params_available['source'] = True
                temp_source_widget = SourceWidget(line.strip())
                self.settings_widget_layout.replaceWidget(self.source_widget, temp_source_widget)
                self.source_widget.deleteLater()
                self.source_widget = temp_source_widget
                self.source_widget.setEnabled(True)
                saved_source_value = run_command(f'py-ini-config get {config_path} "{current_scanner}" source')
                if saved_source_value:
                    try:
                        self.source_widget.source_combobox.setCurrentText(saved_source_value)
                    except Exception:
                        print('Сохранённое значение источника отсутствует в списке.')
                print('so')

            if line.strip().startswith('--resolution'):
                self.scanner_params_available['resolution'] = True
                temp_resolution_widget = ResolutionWidget(line.strip())
                self.settings_widget_layout.replaceWidget(self.resolution_widget, temp_resolution_widget)
                self.resolution_widget.deleteLater()
                self.resolution_widget = temp_resolution_widget
                self.resolution_widget.setEnabled(True)
                saved_resolution_value = run_command(f'py-ini-config get {config_path} "{current_scanner}" resolution')
                if saved_resolution_value:
                    try:
                        self.resolution_widget.resolution_combobox.setCurrentText(saved_resolution_value)
                    except Exception:
                        print('Сохранённое значение разрешения отсутствует в списке.')
                print('re')

    def update_scanners_dict(self, scanners):
        self.scanners_combobox.clear()
        self.scanners_combobox.addItems(list(scanners.keys()))
        self.current_scanner = self.scanners_combobox.currentText().strip()
        self.scanners_dict = scanners
        self.scanners_combobox.currentIndexChanged.connect(self.renew_info_about_scanner)
        self.renew_info_about_scanner()

    def update_scanners_list(self):
        self.disable_all_widgets()
        self.scanners_info_label.setText('Определяем сканеры...')
        self.status_bar.setText('Определение сканеров...')
        self.scanners_combobox.setDisabled(True)
        self.scanners_detect_thread = QThread(parent=self)
        self.detect_scanners = DetectScanners()
        self.detect_scanners.moveToThread(self.scanners_detect_thread)
        self.detect_scanners.finish_signal.connect(lambda scanners: self.update_scanners_dict(scanners))
        self.detect_scanners.finish_signal.connect(lambda: self.scanners_info_label.setText('Выберите сканер: '))
        self.detect_scanners.finish_signal.connect(lambda: self.scanners_combobox.setEnabled(True))
        self.detect_scanners.finish_signal.connect(self.enable_buttons)
        self.detect_scanners.finish_signal.connect(self.detect_scanners.deleteLater)
        self.detect_scanners.finish_signal.connect(self.scanners_detect_thread.quit)
        self.scanners_detect_thread.started.connect(self.detect_scanners.run)
        self.scanners_detect_thread.finished.connect(self.scanners_detect_thread.deleteLater)
        self.scanners_detect_thread.start()

    def save_scan_settings(self):
        run_command(f'touch {config_path}')
        current_scanner = self.scanners_combobox.currentText().strip()
        if self.brightness_widget.isEnabled():
            run_command(
                f'py-ini-config set {config_path} "{current_scanner}" brightness {self.brightness_widget.brightness_slider.value()}')
        else:
            run_command(f'py-ini-config del {config_path} "{current_scanner}" brightness')
        if self.contrast_widget.isEnabled():
            run_command(
                f'py-ini-config set {config_path} "{current_scanner}" contrast {self.contrast_widget.contrast_slider.value()}')
        else:
            run_command(f'py-ini-config del {config_path} "{current_scanner}" contrast')
        if self.source_widget.isEnabled():
            run_command(
                f'py-ini-config set {config_path} "{current_scanner}" source "{self.source_widget.source_combobox.currentText()}"')
        else:
            run_command(f'py-ini-config del {config_path} "{current_scanner}" source')
        if self.resolution_widget.isEnabled():
            run_command(
                f'py-ini-config set {config_path} "{current_scanner}" resolution "{self.resolution_widget.resolution_combobox.currentText()}"')
        else:
            run_command(f'py-ini-config del {config_path} "{current_scanner}" resolution')
        self.status_bar.setText(f'Информация о сканере {current_scanner} сохранена.')

    def disable_all_widgets(self):
        self.renew_scanners_list_btn.setDisabled(True)
        self.save_scan_settings_btn.setDisabled(True)
        self.brightness_widget.setDisabled(True)
        self.contrast_widget.setDisabled(True)
        self.source_widget.setDisabled(True)
        self.resolution_widget.setDisabled(True)

    def enable_buttons(self):
        self.renew_scanners_list_btn.setEnabled(True)
        self.save_scan_settings_btn.setEnabled(True)

    def __init__(self):
        QMainWindow.__init__(self)

        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.central_widget_layout = QGridLayout()
        self.central_widget.setLayout(self.central_widget_layout)
        self.scanners_combobox = QComboBox()

        self.scanners_info_label = QLabel('')
        self.central_widget_layout.addWidget(self.scanners_info_label, 0, 0)
        self.central_widget_layout.addWidget(self.scanners_combobox, 0, 1)

        self.scanner_params_available = {
            'brightness': False,
            'contrast': False,
            'source': False,
            'resolution': False
        }

        self.settings_widget = QWidget()
        self.settings_widget_layout = QVBoxLayout()
        self.settings_widget.setLayout(self.settings_widget_layout)

        self.brightness_widget = BrightnessWidget(0)
        self.brightness_widget.setDisabled(True)
        self.settings_widget_layout.addWidget(self.brightness_widget)

        self.contrast_widget = ContrastWidget(0)
        self.contrast_widget.setDisabled(True)
        self.settings_widget_layout.addWidget(self.contrast_widget)

        self.source_widget = SourceWidget("")
        self.source_widget.setDisabled(True)
        self.settings_widget_layout.addWidget(self.source_widget)

        self.resolution_widget = ResolutionWidget("")
        self.resolution_widget.setDisabled(True)
        self.settings_widget_layout.addWidget(self.resolution_widget)

        self.central_widget_layout.addWidget(self.settings_widget, 1, 0, 1, 2)

        self.renew_scanners_list_btn = QPushButton('Обновить список сканеров')
        self.renew_scanners_list_btn.clicked.connect(self.update_scanners_list)
        self.central_widget_layout.addWidget(self.renew_scanners_list_btn, 2, 0)

        self.save_scan_settings_btn = QPushButton('Сохранить настройки')
        self.save_scan_settings_btn.clicked.connect(self.save_scan_settings)
        self.central_widget_layout.addWidget(self.save_scan_settings_btn, 2, 1)

        horizontal_line = QFrame()
        horizontal_line.setFrameShape(QFrame.HLine)
        self.central_widget_layout.addWidget(horizontal_line, 3, 0, 1, 2)

        self.status_bar = QLabel()
        self.central_widget_layout.addWidget(self.status_bar, 4, 0, 1, 2)

        self.update_scanners_list()
        self.setGeometry(50, 50, 500, 100)
        self.setWindowTitle("Настройка сканера для ПО АРМ ГИА")
        self.setWindowIcon(QIcon('local-scanner-settings.svg'))
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ScannerSettings()
    sys.exit(app.exec_())
